/* ------------------------------------------------------------*/
/*--------------------- Librerias -----------------------------*/
/*-------------------------------------------------------------*/

#include <stdio.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <signal.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include "../Headers/msgqueue.h"
#include <sys/msg.h>
#include "../Headers/shared.h"
#include "../Headers/list.h"
#include "../Headers/sem.h"
#include <sys/shm.h>


/* ------------------------------------------------------------*/
/*--------------------- Constantes ----------------------------*/
/*-------------------------------------------------------------*/

#define HOST_IP "127.0.0.1"
#define HOST_SERVICE "12345"
#define QLEN 32
#define MAX_CLI 10
#define KEY_MSGQ_IN 0x322
#define KEY_MSGQ_OUT 0x222
#define MAX_MSG_SIZE 255
#define SEC_TIMEOUT 0
#define MSEC_TIMEOUT 200
#define CANT_COMM 4
#define SESIONES 2

#define NEW_CONN_P 1
#define CLOSE_CONN_P 2
#define MESSAGE_P 3
#define LIST_USERS_P 4

#define CONNECTION_PRIORITY 1

#define L_MSGQ_KEY 0x122
#define C_MSGQ_KEY 0x022

#define FIFO_CONN "/tmp/conn_req"

#define SHM_CONN 0x333
#define SHM_GIANT 0x444

#define SHM_SIZE SHM_BLOCK*SHM_USERS
#define SHM_USERS 30
#define SHM_BLOCK 300

#define SEM_KEY 0x111

#define TIMEOUT 60

/* ------------------------------------------------------------------------- */
/* ------------------------- Estructuras ----------------------------------- */
/* ------------------------------------------------------------------------- */

struct conn_type{
	pid_t proid;
	char room[10];
	char user_name[20];
};

typedef struct serverInfoT{
	int sock;
}serverInfoT;

typedef struct trans_info{
	int fd;		/* file descriptor */
	int inbox;	/* server-dispatcher inbox queue*/
	int outbox;	/* server-dispatcher outbox queue*/
	char * mem;	/* Share Memory given segment */
	int sem;	/* Semaphore used */
	int fd_aux;	/* In message queue case, for the client-server outbox*/
	int offset;	/* Shared Memory offset */
	int client_pid;	/* Client Process ID */
	long server_pid;	/* Child Server Process ID*/
	int conn_state; /* 0 on startup -> 1 if something wrong happened */
	time_t sec; /* Time of the last received message*/
}trans_info;

/* ------------------------------------------------------------------------- */
/* ------------------------- Variables Globales ---------------------------- */
/* ------------------------------------------------------------------------- */

serverInfoT sInfo;
char * comm[CANT_COMM] = {"Sesiones", "Listar ", "Ingresar ", "Salir"};
char * chatRooms[SESIONES] = {"a", "b"};
/* Aca guardo el tipo de conexion con el que arrancamos el server para despues 
 * saber como tengo que accionar */
char conn_type[5] = {0};
int sigint_flag = 0; /* Para threads habria que usar mutex con esta variable */

/* ------------------------------------------------------------------------- */
/* ---------------------- Funciones de logica del Main Server -------------- */
/* ------------------------------------------------------------------------- */

void serverLogic (char * type);
void serverSHMLogic(void);
void serverFIFOLogic(void);
void serverTCPLogic (void);
void serverMSGQLogic(void);

/* ------------------------------------------------------------------------- */
/* --------------------------- Dispatcher ---------------------------------- */
/* ------------------------------------------------------------------------- */

void dispatcher();

/* ------------------------------------------------------------------------- */
/* -------------------- Funciones de logica de Child Servers --------------- */
/* ------------------------------------------------------------------------- */

void child(struct trans_info * tinfo);
void childSHM(struct trans_info * tinfo);
void childFIFO(struct trans_info * tinfo);
void childTCP(struct trans_info * tinfo);
void childMSGQ(struct trans_info * tinfo);
void ParseRequest(struct trans_info * tinfo, char * msg);

/* ------------------------------------------------------------------------- */
/* ---------------------- Funciones de Inicio ------------------------------ */
/* ------------------------------------------------------------------------- */

void SendUsers(struct trans_info * tinfo, char * room);
void InitChat(struct trans_info * tinfo);
int SendConnect(struct trans_info * tinfo, char * room);
void SendSessions(struct trans_info * tinfo);
void SendDisconnect(struct trans_info * tinfo);
int InitServer(char * type);
int initTCPServer (void);
void createDispatcher();
int initSHMServer(void);

/* ------------------------------------------------------------------------- */
/* ---------------------- Funciones Auxiliares ----------------------------- */
/* ------------------------------------------------------------------------- */

static int IsValidRoom(char * room);
void reaper(int sig);
void handler(int sig);
void dispatcher_handler(int sig);
void child_handler(int sig);
int ConnCp(void *c1, void *c2);
void disconnectRequest (listADT conn, struct q_entry * pr_entry);
void connectRequest (listADT conn, struct q_entry * pr_entry);
int selectWrapper(int sockid, int secs, int microsecs);
int GetOffset(char * mem);
int ListenClient(struct trans_info * tinfo, char * msg);
int SendClient(struct trans_info * tinfo, char * msg);

/* ------------------------------------------------------------------------- */
/* ----------------------------- Main Server ------------------------------- */
/* ------------------------------------------------------------------------- */

int
main(int argc, char * argv[])
{   
	
    /* Valido argumentos recibidos por linea de comandos */
    if (!validArgs (argc, argv[1]))
    	return 1;
    
    /* Declaro el manejador de senal en caso de que un hijo termine */
   (void) signal(SIGCHLD, reaper);
   (void) signal(SIGINT, handler);

   /* Guardo el tipo de conexion que vamos a utilizar*/
   strncpy(conn_type, argv[1], strlen(argv[1]));
   
    /* Seteo el Servidor para que escuche Conexiones */
    /* que pasa con el dispatcher */
    if (InitServer(argv[1]) < 0){
    	fprintf (stdout, "Error: Could not initialize server\n");
    	return 1;
    }
    
    /* Creo el dispatcher que se encarga de reenviar mensajes
     * recibos a todos los servidores hijos conectados con clientes */
    createDispatcher();
     
     serverLogic (argv[1]);
    
     return 0;
}

/* ------------------------------------------------------------------------- */
/* --------------- Funciones de logica del Main Server --------------------- */
/* ------------------------------------------------------------------------- */

void
serverLogic (char * type)
{
	if (!strncmp (type, "TCP", strlen ("TCP"))){
		serverTCPLogic ();
		return ;
	}if(!strncmp(type, "MSGQ", strlen("MSGQ"))){
		serverMSGQLogic();
		return;
	}if(!strncmp(type, "FIFO", strlen("FIFO"))){
		serverFIFOLogic();
		return;
	}if(!strncmp(type, "SHM", strlen("SHM"))){
		serverSHMLogic();
		return;
	}
}

void
serverSHMLogic(void)
{
	struct trans_info * tinfo;
	fprintf(stdout, "Initializing Shared Memory Server\n");
	/* Creo la zona de Memoria Gigante */
	char * mem;
	char * giant;
	int id, offset, semid;
	int cli_pid, flag = 0;
	
	id = shmget(SHM_GIANT, SHM_SIZE, 0666 | IPC_CREAT);
	if ( id == -1){
		perror("Error SHM_GIANT");
		exit(1);
	}
	giant = (char *)shmat(id, NULL, 0666);
	if (giant == (void *)-1){
		perror("Error SHMAT");
		exit(1);
	}else putZeros((char *) giant, SHM_SIZE);
	
	mem = (char *)shmat(sInfo.sock, NULL, 0666);
	if (mem == (void *)-1){
		perror("Error SHMAT");
		exit(1);
	}else putZeros((char *) mem, MAX_MSG_SIZE);

	/* Seteo el Semaforo que voy a utilizar */
	semid = initsem(SEM_KEY);
	if ( semid == -1){
		return ;
	}
	
	while(ALWAYS){
		usleep(500000);
		
		p(semid);
		/* Aca voy a fijarme si me pidieron una conexion */
		if ( mem[0] == 1){
			/* Creo la nueva estructura con la informacion de la transferencia */
			tinfo = calloc(1, sizeof(struct trans_info));
			if ( tinfo == NULL){
				fprintf(stdout, "Failed creating trans_info in TCP\n");
				exit(1);
			}
			/* Ahora inicializo la estructura */
			fprintf(stdout, "%d - %s\n", mem[0], mem+1);
			/* Hay un Nuevo pedido. Guardo el PID */
			tinfo->client_pid = atoi(mem+1);
			/* Creo la respuesta */
			mem[0] = 2;
			tinfo->offset = GetOffset(giant);
			tinfo->mem = giant;
			fprintf(stdout, "offset = %d\n", tinfo->offset);
			sprintf(mem+1, "%d %d", id, tinfo->offset);
			tinfo->mem[tinfo->offset] = 1;
			fprintf(stdout, "marca\n");
			flag = 1;
			fprintf(stdout, "flag = %d\n", flag);
			tinfo->sem = tinfo->client_pid;

		}

		v(semid);
		if (flag == 1){
			fprintf(stdout, "Ahora tendria que hacer el FORK\n");
			/* Tengo que hacer fork()*/
			switch(fork()){
			case -1:
				fprintf (stdout, "Error: Fork: %s", strerror(errno));
				exit(1);
			case 0:
				fprintf(stdout, "Ahora entro a child");
				child(tinfo);
				exit(0);
			default:
				flag = 0;
				break;
			}
		}
	}
}

void
serverFIFOLogic(void)
{
	struct trans_info * tinfo;
	int qty;
	char msg[MAX_MSG_SIZE];
	int cli_pid;

	while(ALWAYS){
		sleep(1);
		errno = 0;
		
		if ( selectWrapper(sInfo.sock, 1, 0) < 0){
			if (errno == EINTR)
				continue;
			else
				fprintf (stdout, "Select Error: %d\n", errno);
		}else {
			qty = read (sInfo.sock, msg, MAX_MSG_SIZE); 
			if (qty < 0 && errno != EAGAIN){
				fprintf (stdout, "errno: %d\n", errno);
				perror ("Error reading socket\n");
				return;
			}else if (qty > 0){
				fprintf(stdout, "lei : %d\n", qty);
				fprintf(stdout, "lei string : %s\n", msg);
				/* Creo la nueva estructura con la informacion de la transferencia */
				tinfo = calloc(1, sizeof(struct trans_info));
				if ( tinfo == NULL){
					fprintf(stdout, "Failed creating trans_info in TCP\n");
					exit(1);
				}
				/* Ahora inicializo la estructura */
				tinfo->client_pid = atoi(msg);
				switch(fork()){
				case -1:
					fprintf (stdout, "Error: Fork: %s", strerror(errno));
					exit(1);
				case 0:	
					child(tinfo);
					exit(0);
				default:
					break;
				}
			}
		}
	}
}

void
serverMSGQLogic(void)
{
	struct trans_info * tinfo;
	int fd;
	int flag;
	struct q_entry r_entry, s_entry;
	int cli_pid, srv_child;
	
	fprintf(stdout, "Se inicializa el Server para Message Queues.\n");
	
	/* Creo la cola para que los server hijos atiendan clientes */
	(void) NewQueue(C_MSGQ_KEY, 0666 | IPC_CREAT);
	
	while(ALWAYS){
		sleep(1);
		errno = 0;
		/* Pregunto si hay algun pedido de conexion */
		flag = GetMsgQueue(sInfo.sock, &r_entry, CONNECTION_PRIORITY);
		fprintf(stdout, "flag : %d\n", flag);
		if (errno != ENOMSG){
    		/* Creo la nueva estructura con la informacion de la transferencia */
    		tinfo = calloc(1, sizeof(struct trans_info));
    		if ( tinfo == NULL){
    			fprintf(stdout, "Failed creating trans_info in TCP\n");
    			exit(1);
    		}
    		/* Ahora inicializo la estructura */
			/*Me llego un pedido de conexion */
			/* Guardo el PID del cliente */
			tinfo->client_pid = atoi(r_entry.text);
			s_entry.mpriority = cli_pid;
			srv_child = fork();
			fprintf(stdout, "fork : %d\n", srv_child);
			switch(srv_child){
			case -1:
				fprintf (stdout, "Error: Fork: %s", strerror(errno));
				exit(1);
			case 0:
				child(tinfo);
				exit(0);
			default:
				/* Ahora le aviso al cliente con quien y por donde
				 * se va a conectar */
				s_entry.mpriority = tinfo->client_pid;
				sprintf(s_entry.text, "%d %d", C_MSGQ_KEY, srv_child);
				SendMsgQueue(sInfo.sock, (void *) &s_entry, IPC_NOWAIT);
				break;
			}
		}
	}
}

void
serverTCPLogic (void)
{
	struct trans_info * tinfo;
    int ssock;
	unsigned int alen;
    struct sockaddr_in fsin;
    struct timeval tv;
    fd_set rfds;
    tv.tv_sec = SEC_TIMEOUT;
    tv.tv_usec = MSEC_TIMEOUT;
    FD_ZERO(&rfds);	


    while (ALWAYS){
    	/* Seteo donde quiero escuchar */
        FD_SET (sInfo.sock, &rfds);
        if(select(sInfo.sock + 1, &rfds, (fd_set *)0, (fd_set *)0, &tv) < 0){
            if (errno == EINTR)
                continue;
            else
                fprintf (stdout, "Select Error: %d\n", errno);
        }
        
        /* Hay algo en el sock, acepto la conexion */
        
        if (FD_ISSET(sInfo.sock, &rfds)){
        	alen = sizeof(fsin);
        	if ((ssock = accept(sInfo.sock, (struct sockaddr *)&fsin, &alen)) < 0)
        	{
        		fprintf (stdout, "Accept Failed\n");
        	    if (errno == ECONNABORTED)
        	    	continue;
        	}else{
        		/* Creo la nueva estructura con la informacion de la transferencia */
        		tinfo = calloc(1, sizeof(struct trans_info));
        		if ( tinfo == NULL){
        			fprintf(stdout, "Failed creating trans_info in TCP\n");
        			exit(1);
        		}
        		/* Ahora inicializo la estructura */
        		tinfo -> fd = ssock;
        		switch(fork()){
        		case -1:
        			fprintf (stdout, "Error: Fork: %s", strerror(errno));
        			exit(1);
        		case 0:	/* Hijo */
      			(void) close(sInfo.sock);
        			child(tinfo);
        			exit(0);
        		default:	/* Padre */
       			(void) close(ssock);
       			break;
        		}
        	}
        }
        
    }	
}

/* ------------------------------------------------------------------------- */
/* ---------------------------- Dispatcher --------------------------------- */
/* ------------------------------------------------------------------------- */

void
dispatcher()
{
	int queue, queue_out;
	struct q_entry s_entry, r_entry;
	char txt[MAX_MSG_SIZE] = {0};
	int action, cli_pid, i;
	listADT conn;
	struct conn_type * new;
	char aux_room[10];
	char * aux;

	
	errno = 0;
	
	/* Creo la lista donde guardo la conexiones a los chatrooms */
	conn = NewList(ConnCp);
	
	/* Creo la cola de mensajes para entrada y salida*/
	queue = NewQueue(KEY_MSGQ_IN, 0666 | IPC_CREAT);

	queue_out = NewQueue(KEY_MSGQ_OUT, 0666 | IPC_CREAT);

	signal(SIGINT, dispatcher_handler);
	
	while(ALWAYS){
		//fprintf(stdout, "La lista tiene %d elementos\n", ListLength(conn));
		usleep(200);
		errno = 0;
		/* Reviso si hay algun mensaje en la cola */
		GetMsgQueue(queue, &r_entry, 0);
		if ( errno != ENOMSG){
			/* Aca hay que parsear la expresion que me mandaron */
			//fprintf(stdout, "dispatcher :%s\n", r_entry.text);
			/* Pedido de Nueva conexion */
			if ( r_entry.text [0] == '1'){
				connectRequest (conn, &r_entry);
				//fprintf(stdout, "Pedido de Conexion\n");		
			}
			
			/* Llego pedido de desconexion */
			else if (r_entry.text[0] == '2'){
				//fprintf(stdout, "Desconexion\n");
				disconnectRequest (conn, &r_entry);
			}
			/* Llego un mensaje nuevo 
			 * Busco en la lista para ver en que chatroom esta*/
			else if (r_entry.text[0] == '3'){
				SetBegin(conn);
				do{
					//fprintf(stdout, "Tomo un elemento\n");
					new = GetDato(conn);
					//fprintf(stdout, "Elemento de lista: %d, %s\n", new->proid, new->room);
				}while (new != NULL && new->proid != r_entry.mpriority);
				if ( new == NULL){
				//	fprintf(stdout, "Donde carajo estas?\n");
				}
				/* Ahora guardo el ChatRoom */
				strcpy(aux_room, new->room);
				//fprintf(stdout, "El que mando el mensaje esta en %s\n", aux_room);
				/* Vuelvo la Lista al principio para empezar a iterar */
				SetBegin(conn);
				do{
					new = GetDato(conn);
					/*if ( new == NULL){
						fprintf(stdout, "Se termino la lista\n");
					}else fprintf(stdout, "Elemento de lista: %d, %s\n", new->proid, new->room);
					*/
					if (new != NULL && (strcmp(new->room, aux_room) == 0)){
						//fprintf(stdout, "Se lo voy a mandar EH!\n");
						/* Si entre aca, es por que tengo que mandarle el mensaje */
						s_entry.mpriority = new->proid;
						strcpy(s_entry.text, r_entry.text+2);
						/* Una vez copiado todo exacto como le llego, lo mando a la cola de salida */
						SendMsgQueue(queue_out, &s_entry, IPC_NOWAIT);
						//fprintf(stdout, "Le mande ; %s\n", s_entry.text);
						//fprintf(stdout, "Fue mandado\n");
					}
				}while (new != NULL);
				/* Ya termine de mandar el mensaje a todos los presentes en ese chatroom */
			}else if(r_entry.text[0] == '4'){
				i = 0;
				SetBegin(conn);
				/* Me paro en el primer caracter del nombre del chatroom*/
				aux = r_entry.text + 2;
				//fprintf(stdout, "Me pidieron: %s\n", aux);
				do{
					/* Aca armo el string */
					new = GetDato(conn);
					if(new != NULL && strncmp(new->room, aux, strlen(aux)) == 0){
						/* Este usuario esta en el ChatRoom requerido */
						//fprintf(stdout, "HAY UNO!\n");
						sprintf(txt + i, "%s\n", new->user_name);
						i += strlen(new->user_name) +1;
					}
				}while(new != NULL);
				if ( i == 0)
					sprintf(txt, "No hay ningun usuario conectado a ese chatroom\n");
                s_entry.text[0] = 1;
				strcpy(s_entry.text+1, txt);
				s_entry.mpriority = r_entry.mpriority;
				SendMsgQueue(queue_out, &s_entry, IPC_NOWAIT);
				fprintf(stdout, "Envie al usuario la lista de usuarios:\n%s\n", s_entry.text);
				putZeros(s_entry.text, MAX_MSG_SIZE);
			}
			
		}

	}
	
	return;
}

/* ------------------------------------------------------------------------- */
/* -------------------- Funciones de logica de Child Servers --------------- */
/* ------------------------------------------------------------------------- */

void
child(struct trans_info * tinfo)
{
	int msg_queue, in_queue;
	struct q_entry s_entry, r_entry;
	
	errno = 0;
	/* Abro la cola donde voy a mandar mis mensajes al dispatcher */
	tinfo->outbox = NewQueue(KEY_MSGQ_IN, 0666);
	/* Esta es la Inbox donde el dispatcher me deja sus mensajes para mi */
	tinfo->inbox = NewQueue (KEY_MSGQ_OUT, 0666);

	/* Inicializo el estado de la conexion */
	tinfo->conn_state = 0;

	if(strcmp(conn_type, "TCP") == 0)
		childTCP(tinfo);
	else if(strcmp(conn_type, "MSGQ") == 0)
		childMSGQ(tinfo);
	else if(strcmp(conn_type, "FIFO") == 0)
		childFIFO(tinfo);
	else if(strcmp(conn_type, "SHM") == 0)
		childSHM(tinfo);
	
	exit(0) ;	
}

/* EN FD esta el PID del cliente para usar en el semaforo */
/* Tengo que abrir de nuevo la zona de memoria usando la key */

void
childSHM(struct trans_info * tinfo)
{
	int id;
	char msg[MAX_MSG_SIZE] = {0};
	
	signal(SIGINT, child_handler);
	
	fprintf(stdout, "Llegue al childSHM\n");
	
	/* Me paro donde debo */
	tinfo->mem += tinfo->offset;
	/* Seteo el Semaforo que voy a utilizar */
	tinfo->sem = initsem(tinfo->client_pid);
	if ( tinfo->sem == -1){
		return ;
	}
	tinfo->server_pid = getpid();
	tinfo->sec = time(NULL);
	while(ALWAYS){
		usleep(200000);
		putZeros(msg, MAX_MSG_SIZE);
		/* Seteo el Semaforo*/
		p(tinfo->sem);
		fprintf(stdout, "mem[1] = %c\n", tinfo->mem[1]);
		if ( tinfo->mem[1] == 1){
			fprintf(stdout, "Llego algo\n");
			/* hay un nuevo comando para leer */
			tinfo->sec = time(NULL);
			strcpy(msg, (tinfo->mem) + 2);
			fprintf(stdout, "%s\n", msg);
			v(tinfo->sem);
			ParseRequest(tinfo, msg);
		}else if (tinfo->mem[1] == 3)
			tinfo->conn_state = 1;
		else v(tinfo->sem);
		if (sigint_flag == 1)
			tinfo->conn_state = 1;
		if ( tinfo->conn_state == 1){
			/* Marco como vacia la zona de memoria que usaba */
			tinfo->mem[0] = 0;
			v(tinfo->sem);
			semctl(initsem(tinfo->client_pid), 1, IPC_RMID, 0);
			free(tinfo);
			return ;
		}
		if ( (time(NULL) - tinfo->sec) > TIMEOUT){
			fprintf(stdout, "Me voy gato...\n");
			/* Hace mucho que no me manda nada...*/
			tinfo->conn_state = 1;
			tinfo->mem[0] = 0;
			return;
		}
		if(sigint_flag == 1)
			tinfo->conn_state = 1;
		
	}
	
}

/* En fd me llega el PID del cliente con el que me voy a conectar */
void
childFIFO(struct trans_info * tinfo)
{
	int fifo_in, fifo_out, flag;
	int qty;
	char msg[MAX_MSG_SIZE];
	char Sfifo_in[20] = {0};
	char Sfifo_out[20] = {0};
	
	signal(SIGINT, child_handler);
	
	/*Armo los Strings para los fifos*/
	sprintf(Sfifo_in, "/tmp/R%d", tinfo->client_pid);
	sprintf(Sfifo_out, "/tmp/W%d", tinfo->client_pid);
	
	/*Creo los fifos*/
	flag = mkfifo(Sfifo_in, 0666);
	if (flag == -1){
		perror("Error: Could not initialize FIFO\n");
		return;
	}
	
	flag = mkfifo(Sfifo_out, 0666);
	if (flag == -1){
		perror("Error: Could not initialize FIFO\n");
		return;
	}
	
	/*los abro*/
	tinfo->fd = open(Sfifo_in, O_RDONLY);
	if (tinfo->fd == -1){
		perror("Error: Could not open FIFO\n");
		return;
	}
	
	tinfo->fd_aux = open(Sfifo_out, O_WRONLY);
	if (tinfo->fd_aux == -1){
		perror("Error: Could not open FIFO\n");
		return;
	}
	tinfo->server_pid = getpid();
	fcntl(tinfo->fd_aux, F_SETFL, O_NONBLOCK);
	fcntl(tinfo->fd, F_SETFL, O_NONBLOCK);
	while(ALWAYS){
		sleep(1);
		errno = 0;
		/* Me fijo si el usuario me mando algo */
		fprintf(stdout, "fifo_in = %d\n", tinfo->fd);
		qty = ListenClient(tinfo, msg);
		if(sigint_flag == 1)
			tinfo->conn_state = 1;
		fprintf(stdout, "qty = %d\n", qty);
		if(qty == -2)
			continue;
		else if (qty == -1){
			tinfo->conn_state = 1 ;
		}else if (qty > 0){
			fprintf(stdout, "Llego esto : %s \n", msg);
			/* Hay que parsear lo que mando para ver que es.
			 * En ParseRequest tambien se le responde al cliente, 
			 * o en caso de solicitar el ingreso a un chatRoom, se 
			 * llama a la funcion que maneje eso. */
			ParseRequest(tinfo, msg);
			/* Esto lo uso para blanquear la linea. 
			 * Es muy cabeza, podriamos mejorarlo */
			putZeros(msg, MAX_MSG_SIZE);
		}
		fprintf(stdout, "STATE = %d\n", tinfo->conn_state);
		if (tinfo->conn_state == 1){
			fprintf(stdout, "Se cierra el hijo de FIFO...");
			close(tinfo->fd);
			close(tinfo->fd_aux);
			remove(Sfifo_in);
			remove(Sfifo_out);
			free(tinfo);
			return ;
		}
		fprintf(stdout, "Quiero imprimir la variable...%d\n", sigint_flag);
		if(sigint_flag == 1)
			tinfo->conn_state = 1;

	}
}

/* En fd me llega el PID del cliente con el que me voy a conectar */
void
childMSGQ(struct trans_info * tinfo)
{
	int queue;
	char msg[MAX_MSG_SIZE] = {0};
	int qty;
	
	signal(SIGINT, child_handler);
	
	fprintf(stdout, "Entre al childMSGQ\n");
	/* Me conecto a la Cola donde escucho a mi cliente */
	tinfo->server_pid = getpid();
	tinfo->fd = NewQueue(C_MSGQ_KEY, 0666 | IPC_CREAT);
	fprintf(stdout, "Tiempo : %d\n", tinfo->sec);
	tinfo->sec = time(NULL);
	while(ALWAYS){

		usleep(500000);
		/* Me fijo si hay algun mensaje del Cliente */
		qty = ListenClient(tinfo, msg);
		if(sigint_flag == 1)
			tinfo->conn_state = 1;
		fprintf(stdout, "%d\n", qty);
		if(qty == -2)
			continue;
		else if (qty == -1){
			tinfo->conn_state = 1 ;
		}else if (qty > 0){
			tinfo->sec = time(NULL);
			fprintf(stdout, "Llego esto : %s \n", msg);
			/* Hay que parsear lo que mando para ver que es.
			 * En ParseRequest tambien se le responde al cliente, 
			 * o en caso de solicitar el ingreso a un chatRoom, se 
			 * llama a la funcion que maneje eso. */
			ParseRequest(tinfo, msg);
			/* Esto lo uso para blanquear la linea. 
			 * Es muy cabeza, podriamos mejorarlo */
			putZeros(msg, MAX_MSG_SIZE);
		}
		if (tinfo->conn_state == 1){
			/* Se termino la conexion inesperadamente */
			CloseQueue(tinfo->fd);
			free(tinfo);
			return ;
		}
		fprintf(stdout, "%d\n", time(NULL) - tinfo->sec);
		if ( (time(NULL) - tinfo->sec) > TIMEOUT){
			/* Hace mucho que no me manda nada...*/
			CloseQueue(tinfo->fd);
			tinfo->conn_state = 1;
			return;
		}
		if(sigint_flag == 1)
			tinfo->conn_state = 1;
	}
}

void
childTCP(struct trans_info * tinfo)
{
	/* Ya esta iniciada la conexion.  Tengo que esperar que
	 * me entre algun comando */
	char msg[MAX_MSG_SIZE] = {0};
	int qty;

	signal(SIGINT, child_handler);
	
	tinfo->server_pid = getpid();
	fcntl(tinfo->fd, F_SETFL, O_NONBLOCK);

	while(ALWAYS){
		/* Pregunto si hay algo para leer en el fd */
		
		qty = ListenClient(tinfo, msg);
		if(qty == -2)
			tinfo->conn_state = 1 ;
		else if (qty == -1){
			tinfo->conn_state = 1 ;
		}else {
			/* Hay que parsear lo que mando para ver que es.
			 * En ParseRequest tambien se le responde al cliente, 
			 * o en caso de solicitar el ingreso a un chatRoom, se 
			 * llama a la funcion que maneje eso. */
			ParseRequest(tinfo, msg);
			/* Esto lo uso para blanquear la linea. 
			 * Es muy cabeza, podriamos mejorarlo */
			putZeros(msg, MAX_MSG_SIZE);
		}
		if (tinfo->conn_state == 1){
			fprintf(stdout, "Cerrando Child Server TCP...\n");
			close(tinfo->fd);
			free(tinfo);
			/* Se termino la conexion inesperadamente */
			return ;
		}
		fprintf(stdout, "Quiero imprimir la variable...\n");
		if(sigint_flag == 1)
			tinfo->conn_state = 1;
	}
}

/* ------------------------------------------------------------------------- */
/* ---------------------- Funciones de Inicio ------------------------------ */
/* ------------------------------------------------------------------------- */

int
InitServer(char * type)
{	
	if (!strncmp (type, "TCP", strlen ("TCP"))){
		sInfo.sock = initTCPServer ();
		if(sInfo.sock == -1)
			return -1;
		return 1;
	}else if(!strncmp(type, "MSGQ", strlen("MSGQ"))){
		sInfo.sock = initMSGQServer();
		if(sInfo.sock == -1)
			return -1;
		return 1;
	}else if(!strncmp(type, "FIFO", strlen("FIFO"))){
		sInfo.sock = initFIFOServer();
		if(sInfo.sock == -1)
			return -1;
		return 1;
	}else if(!strncmp(type, "SHM", strlen("SHM"))){
		sInfo.sock = initSHMServer();
		if(sInfo.sock == -1)
			return -1;
		return 1;
	}
}

int
initSHMServer(void)
{
	int shmid;
	
	shmid = shmget(SHM_CONN, MAX_MSG_SIZE, 0666 | IPC_CREAT);
	if (shmid == -1){
		perror("Error: Could no initialize Shared Memory Segment");
		return -1;
	}
	
	return shmid;
}

int
initFIFOServer(void)
{
	int fd;
	
	/* Creo el FIFO */
	fd = mkfifo(FIFO_CONN, 0666);
	if (fd == -1){
		perror("Error: Could not initialize FIFO\n");
		fprintf (stdout, "errno: %d\n", errno);
		return -1;
	}
	
	fd = open(FIFO_CONN, O_RDWR | O_NONBLOCK);
	if (fd == -1){
		perror("Error: Could not open FIFO\n");
		return -1;
	}
	
	return fd;
}


int
initMSGQServer (void)
{
	int fd;
	
	/* Creo la MSGQ donde voy a escuchar */
	fd = NewQueue(L_MSGQ_KEY, 0666 | IPC_CREAT);
	if ( fd == -1){
		perror("Error: Could not initialize Message Queue\n");
		return -1;
	}
	return fd;
}

int
initTCPServer (void)
{
	int sock;
	if ((sock = passiveTCP(HOST_SERVICE, QLEN, HOST_IP)) == 0)
	{
		perror ("Error: Could not initialize server\n");
		return -1;
	}
	return sock;
}

void
createDispatcher()
{
	switch(fork()){
	case -1:
		fprintf (stdout, "Error: Fork: %s", strerror(errno));
		exit(1);
	case 0:
		dispatcher();
		exit(0);
	}
	return ;
}

/* ------------------------------------------------------------------------- */
/* ---------------------- Funciones Auxiliares ----------------------------- */
/* ------------------------------------------------------------------------- */

void
reaper(int sig)
{
        int     status;
        while (wait3(&status, WNOHANG, (struct rusage *)0) > 0)
                ;
}

void
handler(int sig)
{
	fprintf(stdout, "Cerrando ...\n");
	if (!strncmp (conn_type, "TCP", strlen ("TCP"))){
		close(sInfo.sock);
	}else if(!strncmp(conn_type, "MSGQ", strlen("MSGQ"))){
		CloseQueue(sInfo.sock);
		CloseQueue(NewQueue(C_MSGQ_KEY, 0666 | IPC_CREAT));
	}else if(!strncmp(conn_type, "FIFO", strlen("FIFO"))){
		close(sInfo.sock);
		remove(FIFO_CONN);
	}else if(!strncmp(conn_type, "SHM", strlen("SHM"))){
		shmctl(sInfo.sock, IPC_RMID, NULL);
		shmctl(shmget(SHM_GIANT, SHM_SIZE, 0666), IPC_RMID, NULL);
		semctl(initsem(SEM_KEY), 1, IPC_RMID, NULL);
	}
	sigint_flag = 1;
	exit(0);
}

void
dispatcher_handler(int sig)
{
	fprintf(stdout, "Cerrando Dispatcher...\n");
	int a, b;
	
	a = NewQueue(KEY_MSGQ_IN, 0666 | IPC_CREAT);

	b = NewQueue(KEY_MSGQ_OUT, 0666 | IPC_CREAT);
	
	(void) CloseQueue(a);
	(void) CloseQueue(b);
	exit(0);
}

void
child_handler(int sig)
{
	fprintf(stdout, "Cerrando Hijos...\nSeteo la variable\n");
	sigint_flag = 1;
	return ;
}

int
ConnCp(void *c1, void *c2)
{
	struct conn_type * s1, * s2;
	
	s1 = c1;
	s2 = c2;
	
	if ( s1->proid == s2->proid )
		return 0;
	return -1;
	
}

void
disconnectRequest (listADT conn, struct q_entry * pr_entry)
{
	struct conn_type * new;
	
	new = calloc(sizeof(struct conn_type), 1);
	if (new == NULL)
	{
		fprintf(stdout, "Fail allocating memory\n");
	}else {
		new->proid = pr_entry->mpriority;
		(void) Delete (conn, new);
		fprintf(stdout, "Me llego un pedido de desconexion de %d\n", new->proid);
	}

	free(new);
	
	return ;
}

/* Suponiendo que el servidor hijo me manda algo como 1-ChatRoomA Juancito */

void
connectRequest (listADT conn, struct q_entry * pr_entry)
{
	struct conn_type * new;
	char *aux;
	int i = 0;
	
	fprintf(stdout, "Llegue : %s\n", pr_entry->text);
	
	new = calloc(sizeof(struct conn_type), 1);
	if (new == NULL)
		fprintf(stdout, "Fail allocating memory\n");
	else {
		while(pr_entry->text[i] != 0 && pr_entry->text[i] != ' ')
			i++;
		if(pr_entry->text[i] == ' '){
			strcpy(new->user_name, pr_entry->text +i+1);
			pr_entry->text[i] = 0;
		}
		strncpy(new->room, pr_entry->text +2, strlen(pr_entry->text+2));
		new->proid = pr_entry->mpriority;
		fprintf(stdout, "Voy a guardar : pid: %d chatroom: %s y con user name : %s\n", new->proid, new->room, new->user_name);
		(void) Insert (conn, new);
		fprintf(stdout, "Me llego un pedido de conexion de %d para el cuarto %s\n", new->proid, new->room);
	}			
	return ;
}
/*Desarrollada por el grupo*/
int
selectWrapper(int sockid, int secs, int microsecs)
{
	fd_set rfds;
	struct timeval tv;
	
	FD_ZERO(&rfds);
	FD_SET(sockid,&rfds);
			
	tv.tv_sec = secs;
	tv.tv_usec = microsecs;
	
	return  select(sockid+1,&rfds,NULL,NULL,&tv);
	
}

void
ParseRequest(struct trans_info * tinfo, char * msg)
{
	int i;
	int flag = 0;
	char wcomm [] = "El comando es invalido\n";

	fprintf(stdout, "Esto me llego a ParseRequest: %s\n", msg);
	
	for(i=0; i< CANT_COMM +1 && flag == 0; i++){
		if (strncmp(msg, comm[i], strlen(comm[i])) == 0){
			/* Es un comando valido */
			switch(i){
			case 0 :
				/* El cliente pregunta por las sesiones disponibles */
				SendSessions(tinfo);
				if ( tinfo->conn_state == 1){
					/* Se produjo un error */
					return;
				}
				flag = 1;
				break;
			case 1:
				/* El cliente quiere saber quienes estan logueados
				 * a que sesion */
				SendUsers(tinfo, msg + strlen(comm[i]));
				if ( tinfo->conn_state == 1){
					/* Se produjo un error */
					return;
				}
				flag = 1;
				break;
			case 2: 
				/* El cliente quiere ingresar en una sesion */
				if(SendConnect(tinfo, msg +  strlen(comm[i])) == 1){
					InitChat(tinfo);
				}
				//fcntl(tinfo->fd, F_SETFL, 0);
				if ( tinfo->conn_state == 1){
					/* Se produjo un error */
					return;
				}
				flag = 1;
				break;
			case 3:
				/* El cliente quiere salir de su sesion */
				tinfo->conn_state = 1;
				return;
			}
		}else if(msg[0] == 2){
			tinfo->conn_state = 1;
			return;
		}
			
	}
	return;
}

void
SendSessions(struct trans_info * tinfo)
{
	int i = 0;
	int index = 1;
	char msg[MAX_MSG_SIZE] = {0};
	char * auxi;
	signal (SIGPIPE, SIG_IGN);
	errno = 0;
	auxi = msg;
	/* Armo el mensaje a enviar con la lista de los chatrooms */
	auxi[0] = 2;
	fprintf(stdout, "voy a mandar las sesiones\n");
	
	while ( i < SESIONES){
		sprintf(auxi + index, "%s\n", chatRooms[i]);
		index += strlen(chatRooms[i]) +1 ;
		i++;	
	}
	/* Una vez que esta armado el string, se lo devuelvo al cliente */
	i = SendClient(tinfo, msg);
	if ( i != strlen(msg)){
		/* No pude escribir todo en el fd */
		if ( i == -2 ){
			/* El otro extremo cerro la conexion */
			SendDisconnect(tinfo);
			tinfo->conn_state = 1;
			return ;
		}
	}
	return;
}

void
SendDisconnect(struct trans_info * tinfo)
{
	struct q_entry disconnect;
	int pid = getpid();
	char opt[10];
	int qty;
	
	fprintf(stdout, "Me llego un pedido de desconexion\n");
	
	disconnect.mpriority = tinfo->server_pid;
	sprintf(disconnect.text, "%d", CLOSE_CONN_P);
	
	if (SendMsgQueue(tinfo->outbox, &disconnect, IPC_NOWAIT) == -1){
		/* Se produjo un error */
		tinfo->conn_state = 1;
		sprintf(opt, "%d", 0);
	}else {
		sprintf(opt, "%d", 1);
	}

	return;
}

int
SendConnect(struct trans_info * tinfo, char * room)
{
	struct q_entry connect;
	char opt[10];
	errno = 0;
	int qty;
	opt[0] = 3;
	/* Preparo el mensaje para enviarlo al dispatcher */
	sprintf(connect.text, "1-%s", room);
	connect.mpriority = tinfo->server_pid;
	fprintf(stdout, "Esto es lo que me llega : %s\n", room);
	/* Hay que validar que sea un Chatroom valido */
	if(!IsValidRoom(room)){
		sprintf(opt+1, "%c",'0');
		SendClient(tinfo, opt);
		return 0;
	}
	
	if (SendMsgQueue(tinfo->outbox, &connect, IPC_NOWAIT) == -1){
		/* Se produjo un error */
		tinfo->conn_state = 1;
		sprintf(opt+1, "%c", '0');
	}else {
		sprintf(opt+1, "%c", '1');
	}
	fprintf(stdout, "Voy a mandarle al cliente : %s\n", opt);
	qty = SendClient(tinfo, opt);
	if(qty == -1 ){
		tinfo->conn_state = 1;
	}
	
	return (int) atoi(opt+1);
}

static int
IsValidRoom(char * room)
{
	int i;
	for(i=0; i<SESIONES; i++){
		if(strncmp(room, chatRooms[i], strlen(chatRooms[i])) == 0)
			return 1;
	}
	return 0;
}
void
SendUsers(struct trans_info * tinfo, char * room)
{
	struct q_entry s_entry;
	s_entry.mpriority = tinfo->server_pid;
	int qty;
	
	sprintf(s_entry.text, "4-%s", room);
	errno = 0;
	SendMsgQueue(tinfo->outbox, &s_entry, IPC_NOWAIT);
	/* Como el Server podria tardar en armar la lista, habria 
	 * que hacer esta funcion que sigue BLOQUEANTE.  Por el
	 * momento, en el modulo es no bloqueante. Esta forma 
	 * en la que lo hago es muy cabeza*/
	do{
		sleep(1);
		GetMsgQueue(tinfo->inbox, &s_entry, tinfo->server_pid);
		fprintf(stdout, "Errno vale : %d\n", errno);
	}while(errno == ENOMSG);
	/* Aca hay que mandarselo al cliente en vez de imprimirlo */
	fprintf(stdout, "Esto le voy a mandar a %d : %s\n", tinfo->client_pid, s_entry.text);
	qty=SendClient(tinfo, s_entry.text);
	if (qty == -1)
		tinfo->conn_state = 1;
	return;
}



void
InitChat(struct trans_info * tinfo)
{
	int pid = getpid();
	int qty;
	char msg[MAX_MSG_SIZE], error[] = "Debe ingresar un comando valido\n";
	struct q_entry r_entry;

	if(strcmp(conn_type, "SHM") == 0)
		v(tinfo->sem);
	
	signal(SIGPIPE, SIG_IGN);
	
	fprintf(stdout, "Entre a InitChat\n");
	
	while(ALWAYS){
		if ( sigint_flag == 1){
			tinfo->conn_state = 1;
			return ;
		}
		usleep(100000);
		/* Tengo que preguntar si hay algo en la 
		 * cola de mensajes para mi */
		errno = 0;
		putZeros(r_entry.text, MAX_MSG_SIZE);
		qty = 0;
		GetMsgQueue(tinfo->inbox, &r_entry, tinfo->server_pid);
    	if ( errno != ENOMSG ){
    		fprintf(stdout, "esto estaba en la cola ; %s\n", r_entry.text);
    		/* Tengo algo que mandar al cliente */
    		qty=SendClient(tinfo, r_entry.text);
        	fprintf(stdout, "aqty = %d\n", qty);
    		if ( qty == -1 ){
    			fprintf(stdout, "Fallo el primer write\n");
    			/* El otro extremo cerro la conexion */
    			SendDisconnect(tinfo);
    			tinfo->conn_state = 1;
    			return ;
    		}
    	}
		putZeros(msg, MAX_MSG_SIZE);

		int flag;
		
		qty = 0;
		
		/* Seteo para que el Listen Client no sea bloqueante */
		
    	fcntl(tinfo->fd, F_SETFL, O_NONBLOCK);
    	if(strcmp(conn_type, "FIFO") == 0){
        	fcntl(tinfo->fd_aux, F_SETFL, O_NONBLOCK);
    		qty = ListenClient(tinfo, msg);	
    	}
    	else qty = ListenClient(tinfo, msg);
		
    	fprintf(stdout, "%d\n", qty);
    	
		if(qty == -2)
			continue;
		else if (qty == -1){
    		fprintf (stdout, "Error reading socket\n");
			SendDisconnect(tinfo);
			tinfo->conn_state = 1;
			return ;
		}else if (qty > 0){
			fprintf(stdout, "%d\n", msg[0]);
    		if ((int) msg[0] != 1){
    			/* Es un comando */
    			/* Solo dejo pasar los que puede mandarme */
    			fprintf(stdout, "Me llego un Comando!! : %s\n", msg);
    			if ( strncmp(msg, "Sesiones", strlen("Sesiones")) == 0 || \
    					strncmp(msg, "Listar ", strlen("Listar ")) == 0 || \
    					strncmp(msg, "Salir", strlen("Salir")) == 0){
    				if(strncmp(msg, "Salir", strlen("Salir")) == 0){
    					/* El guacho no quiere que le responda!*/
    					SendDisconnect(tinfo);
    					return;
    				}
    				ParseRequest(tinfo, msg);
    			}else{
    				qty = SendClient(tinfo, error);
    				if ( qty == -1 ){
    					fprintf(stdout, "Fallo el segundo write\n");
    					/* El otro extremo cerro la conexion */

    					SendDisconnect(tinfo);
    					if(strcmp (conn_type, "SHM") == 0)
    						putZeros (tinfo->mem+1, MAX_MSG_SIZE-2);
    					tinfo->conn_state = 1;
    					return ;
    				}
    			}
    		}else if((int) msg[0] == 1){
    			fprintf(stdout, "Es un mensaje!\n");
    			putZeros(r_entry.text, MAX_MSG_SIZE);
    			/* Es un mensaje */
    			r_entry.mpriority = pid;
    			strcpy(r_entry.text+2, msg+1);
    			r_entry.text[0] = '3';
    			r_entry.text[1] = '-';
    			fprintf(stdout, "msg: %s\n", msg+1);
    			(void)SendMsgQueue(tinfo->outbox, &r_entry, IPC_NOWAIT);
    		}
		}
    }
}
/* Esta funcion se ocupa de escuchar de acuerdo 
 * a la forma establecida al comenzar el servidor */
/* -2 si el select aborta por recibir una senal
 * -1 si hubo una desconexion del otro lado
 * qty e caso de exito
 * */

/* EL READ ES BLOQUEANTE */
int
ListenClient(struct trans_info * tinfo, char * msg)
{
	putZeros(msg, MAX_MSG_SIZE);
	fprintf(stdout, "Entre a ListenClient\n");
	struct q_entry r_entry;
	int qty = 0;
	errno = 0;
	if(strncmp(conn_type, "TCP", strlen("TCP")) == 0){
		/* Estoy utilizando TCP */
		if ( selectWrapper(tinfo->fd, 1, 0) < 0){
			if (errno == EINTR)
				return -2;
			else
				fprintf (stdout, "Select Error: %d\n", errno);
		}else {
			/*Hay algo para leer, lo guardo en msg*/
			qty = read (tinfo->fd, msg, MAX_MSG_SIZE); 
			if (qty <= 0 && errno != EAGAIN){
				perror("CAPUT");
				fprintf (stdout, "Error reading socket\n");
				return -1;
			}
			fprintf(stdout, "Me llego esto en el READ : %s\n", msg);
		}
	}else if(strncmp(conn_type, "MSGQ", strlen("MSGQ")) == 0){
		/* Es MSG QUEUE */
		qty = GetMsgQueue(tinfo->fd, &r_entry, tinfo->server_pid);
		if(qty == -1){
			/*Hubo un error*/
			if (errno == ENOMSG)
				return 0;
			else return -1;
		}
		strcpy(msg, r_entry.text);
		tinfo->sec = time(NULL);
	}else if(strncmp(conn_type, "FIFO", strlen("FIFO")) == 0){
		/* Estoy utilizando FIFO */
		if ( selectWrapper(tinfo->fd, 1, 0) < 0){
			if (errno == EINTR)
				return -2;
			else
				fprintf (stdout, "Select Error: %d\n", errno);
		}else {
			/*Hay algo para leer, lo guardo en msg*/
			qty = read (tinfo->fd, msg, MAX_MSG_SIZE); 
			//Modifico esto para probar. quizas explote al TCP
			if (qty <= 0 && errno != EAGAIN){
				perror("CAPUT");
				fprintf (stdout, "Error reading socket\n");
				return -1;
			}
		}
	}else if(strncmp(conn_type, "SHM", strlen("SHM")) == 0){
		p(tinfo->sem);
		if ( tinfo->mem[1] == 1){
			fprintf(stdout, "Llego algo del Cliente\n");
			/* hay un nuevo comando para leer */
			strcpy(msg, tinfo->mem + 2);
			fprintf(stdout, "%s\n", msg);
			tinfo->sec = time(NULL);
		}else if(tinfo->mem[1] == 3){
			/* El cliente se fue */
			tinfo->conn_state = 1;
		}
		v(tinfo->sem);
		return strlen(msg);
	}
	
	return qty == -1 ? 0:qty;
}

int
SendClient(struct trans_info * tinfo, char * msg)
{
	int qty = 0;
	struct q_entry s_entry;
	
	signal(SIGPIPE, SIG_IGN);
	
	fprintf(stdout, "Entre en SendClient: Voy a mandar %s\n", msg);
	
	if(strncmp(conn_type, "TCP", strlen("TCP")) == 0){
		qty = write(tinfo->fd, msg, strlen(msg) + 1);
		fprintf(stdout, "Mande : %d\n", qty);
		if ( qty != strlen(msg) + 1){
			if (errno == EPIPE){
				/*No hay nadie escuchando*/
				return -1;
			}else return -2;
		}else return qty;
	}else if(strncmp(conn_type, "MSGQ", strlen("MSGQ")) == 0){
		/* Es MSG QUEUE */
		s_entry.mpriority = tinfo->client_pid;
		strcpy(s_entry.text, msg);
		qty = SendMsgQueue(tinfo->fd, &s_entry, IPC_NOWAIT);
		fprintf(stdout, "qty vale en el SendClient: %d\n", qty);
		if (qty == -1 && errno == EIDRM){
			return -1;
		}
		return 1;
	}else if(strncmp(conn_type, "FIFO", strlen("FIFO")) == 0){
		qty = write(tinfo->fd_aux, msg, strlen(msg) + 1);
		if ( qty != strlen(msg) + 1){
				if (errno == EPIPE){
					/*No hay nadie escuchando*/
					return -1;
				}else return -2;
		}else return qty;
	}else if(strncmp(conn_type, "SHM", strlen("SHM")) == 0){
		/* Meto en la direccion de memoria lo que me pidio */
		/* Hay que hacer el semaforo por afuera */
		p(tinfo->sem);
		tinfo->mem[1] = 2;
		strcpy(tinfo->mem +2, msg);
		v(tinfo->sem);
		kill(tinfo->client_pid, SIGUSR1);
		return strlen(msg);
	}
}

int
GetOffset(char * mem)
{
	int index = 0;
	/* voy ciclando mientras el primer flag del bloque este en 1 */
	while(mem[index * SHM_BLOCK] != 0)
		index++;
	return index * SHM_BLOCK;
}
